還記得很久很久以前,
我們曾經在view做過對po文編輯或刪除的限制,
不過這樣只是眼不見為淨而已,還是可以靠輸入網址去進入想看的頁面。
所以我們在controller加上這一行:
before_action :authenticate_user!
現在只有一個post要處理,
假如是大一點的project該怎樣做?
如果一樣在每個view和controller都要加上限制,
那真的是煩死人的事情,萬一有哪裡忘記加上權限管理,
你沒有辦法一目了然地找到。
所以,有沒有什麼辦法把所有的權限管理給集中起來,再也不分view和controller呢?
我不是結巴,是有個gem叫做cancancan。(之前叫做cancan,不過已經太久沒有維護了)
一樣先把cancancan加入Gemfile、安裝,
這裡就不再贅述要怎麼做了。
接著執行: rails g cancan:ability
會產生一隻aibility.rb的檔案,
class Ability
include CanCan::Ability
def initialize(user)
# Define abilities for the passed in user here. For example:
#
# user ||= User.new # guest user (not logged in)
# if user.admin?
# can :manage, :all
# else
# can :read, :all
# end
#
# The first argument to `can` is the action you are giving the user
# permission to do.
# If you pass :manage it will apply to every action. Other common actions
# here are :read, :create, :update and :destroy.
#
# The second argument is the resource the user can perform the action on.
# If you pass :all it will apply to every resource. Otherwise pass a Ruby
# class of the resource.
#
# The third argument is an optional hash of conditions to further filter the
# objects.
# For example, here the user can only update published articles.
#
# can :update, Article, :published => true
#
# See the wiki for details:
# https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities
end
end
其實打到這裡已經可以結束了,
因為看Readme和註解其實就講的很清楚XD
簡單的權限管理是很直觀能處理的,
像是這樣:
if user.blank? #驗證user是不是有登入,如果沒有的話執行下方這一段
cannot :manage, :all #先將執行所有權限的能力取消
basic_read_only #只能基本的看Post(包括show index......等)
else #下方就是有登入的user能做的事情
can :create, Post # 包括new跟create
can :update, Post do |post|
(post.user_id == user.id) # 讓user只能編輯自己的post(下方不贅述啦)
end
can :destroy, Post do |post|
(post.user_id == user.id)
end
basic_read_only
end
如果有太多重複的方法也可以抽出來放在下方,就跟之前在controller抽出來。
protected
def basic_read_only
can :read, Post
end
最後要把驗證放進去controller該怎麼做呢?
就是在posts_controller.rb裡面加上
authorize_resource :post
因為cancan認的是resource的名字,所以記得要將變數命名成@post。
最後就可以把剛剛在view裡面post.user\_id == current\_user.id
給拿掉,
換成
can? :update, post
如果只做到這樣的話,那還是沒有做完最核心的審核發文功能。
所以下來我們要捲起袖子來改一些東西啦!
要想把admin給做出來,其實有很多種方式,
有興趣知道其他方法的可以去參考devise的wiki裡面怎麼寫。
(講到使用者其實也就是那幾個gem用來用去XD)
而admin和前台的layout當然要做一些區別,
在rails裡面做法很簡單,
假如說我們有個layout版型叫做admin.html.erb放在app/views/layouts/底下,
我們只要在controller底下呼叫layout 'admin'
就能夠使用了,
所以在這裡我們將在admin/posts_controller底下加入這一行。
But,這樣當專案變大,每次新增就會都要重加一次,有沒有什麼好的解法呢?
沒有錯,又是繼承,在ruby裡面繼承的符號長這樣:son **<** parent
,
這代表son繼承自parent的意思。
所以這裡我們打開admin/posts_controller來看,
發現他跟其他controller一樣都繼承自application controller,
為了將前台後台分開,我們將新增一個一樣繼承自application controller的admin controller,
可以把它當成是「後台的application controller」,
所有跟後台相關的controller都可以繼承自admin controller,
在這裡加上layout和是否為admin的限制就可將前台後台分開了(model和view部分我們已經處理完啦)
好的,現在我們的客製化後台已經有了個雛形,
下一篇將繼續完成後台的管理功能。
參考資料:
CanCanCan:
http://blog.xdite.net/posts/2012/07/30/cancan-rule-engine-authorization-based-library-2/
https://github.com/CanCanCommunity/cancancan
實作admin角色
https://github.com/plataformatec/devise/wiki/How-To:-Add-an-Admin-Role